package com.greenzebras.geocache;

import java.util.Iterator;
import java.util.List;

import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.OverlayItem;
import com.greenzebras.geocache.cachedata.Cache;
import com.greenzebras.geocache.cachedata.CacheCoordinate;
import com.greenzebras.geocache.constant.GeocacheConstants;
import com.greenzebras.geocache.datastore.GeocacheCacheRequestResponseListener;
import com.greenzebras.geocache.datastore.persistence.GeocacheDataService;

public class GeocacheMapViewActivity extends MapActivity implements
		LocationListener, GeocacheCacheRequestResponseListener {

	MapView mapView;
	GeocacheItemizedOverlay itemizedOverlay;
	MyLocationOverlay myLocationOverlay;
	LocationManager locationManager;
	MapController controller;
	String towers;
	Drawable drawable;
	Drawable currentLocationDrawable;
	private CacheCoordinate currentLocation = new CacheCoordinate();

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.mapview);
		initalizeToogleButton();

		mapView = (MapView) findViewById(R.id.mapview);
		mapView.setBuiltInZoomControls(true);
		mapView.setSatellite(false);

		// set the zoom and center
		controller = mapView.getController();
		controller.setZoom(GeocacheConstants.DEFAULT_ZOOM_VALUE);
		controller.setCenter(mapView.getMapCenter());

		// add current location
		myLocationOverlay = new MyLocationOverlay(this, mapView);
		mapView.getOverlays().add(myLocationOverlay);

		drawable = getResources().getDrawable(R.drawable.marker);
		currentLocationDrawable = getResources().getDrawable(
				R.drawable.current_location_marker);

		Location location = retrieveCurrentLocation();

		if (location != null) {
			updateCurrentLocation(location);
		} else {
			Toast.makeText(GeocacheMapViewActivity.this,
					R.string.location_provider_unavailable_message,
					Toast.LENGTH_LONG).show();
		}

		// create the itemized overlay
		itemizedOverlay = new GeocacheItemizedOverlay(this, drawable, mapView);
		mapView.getOverlays().add(itemizedOverlay);
	}

	private Location retrieveCurrentLocation() {
		Location location = null;
		// use intent
		if (getIntent().hasExtra(
				GeocacheConstants.CURRENT_LOCATION_FOR_MAP_VIEW)) {
			location = extractLocationFromIntent(getIntent());
		} else {
			// retrieve location
			locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
			Criteria crit = new Criteria();

			towers = locationManager.getBestProvider(crit, false);
			location = locationManager.getLastKnownLocation(towers);
			// locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
		}
		return location;
	}

	private Location extractLocationFromIntent(Intent intent) {
		Location location = new Location("");
		CacheCoordinate currentLocationCoordinate = (CacheCoordinate) getIntent()
				.getExtras().get(
						GeocacheConstants.CURRENT_LOCATION_FOR_MAP_VIEW);
		location = new Location("");
		location.setLatitude(currentLocationCoordinate.getGeoPoint()
				.getLatitudeE6() / 1E6);
		location.setLongitude(currentLocationCoordinate.getGeoPoint()
				.getLongitudeE6() / 1E6);
		return location;
	}

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}

	@Override
	protected void onResume() {
		super.onResume();
		myLocationOverlay.enableMyLocation();
		myLocationOverlay.enableCompass();
		if (null != locationManager) {
			locationManager.requestLocationUpdates(towers, 500, 1, this);
		}
	}

	@Override
	protected void onPause() {
		super.onPause();
		myLocationOverlay.disableMyLocation();
		myLocationOverlay.disableCompass();
		if (null != locationManager) {
			locationManager.removeUpdates(this);
		}
	}

	@Override
	protected boolean isLocationDisplayed() {
		return true;
	}

	@Override
	public void onLocationChanged(Location location) {
		updateCurrentLocation(location);
	}

	@Override
	public void onProviderDisabled(String provider) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onProviderEnabled(String provider) {
		// TODO Auto-generated method stub

	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
		// TODO Auto-generated method stub

	}

	private void requestLocalGeocaches() {
		GeocacheDataService.INSTANCE.getLocalCaches(this, currentLocation);
	}

	private void updateMapviewCenter() {
		controller.setCenter(currentLocation.getGeoPoint());
	}

	private void updateCurrentLocation(Location location) {
		currentLocation.setGeoPoint(locationToGeoPoint(location));

		OverlayItem overlayItem = new OverlayItem(
				currentLocation.getGeoPoint(), "", "");
		CustomPinPoint custom = new CustomPinPoint(currentLocationDrawable,
				GeocacheMapViewActivity.this);
		custom.insertPinpoint(overlayItem);
		mapView.getOverlays().add(custom);

		updateMapviewCenter();

		requestLocalGeocaches();
	}

	private GeoPoint locationToGeoPoint(Location location) {
		return new GeoPoint(
				locationCoordinateToGeopointCoordinate(location.getLatitude()),
				locationCoordinateToGeopointCoordinate(location.getLongitude()));
	}

	private int locationCoordinateToGeopointCoordinate(double locationCoordinate) {
		return (int) (locationCoordinate * GeocacheConstants.LOCATION_COORD_TO_GEOPOINT_COORD_MULTIPLIER);
	}

	@Override
	public void processCacheRequestResponse(Cache cache) {
		// empty implementation - currently not used
	}

	@Override
	public void processCachesRequestResponse(List<Cache> caches) {
		GeoPoint point = null;
		Iterator<Cache> itr = caches.iterator();
		while (itr.hasNext()) {
			Cache cache = (Cache) itr.next();
			point = cache.getCacheCoordinate().getGeoPoint();
			if (point != null) {
				OverlayItem overlayitem = new OverlayItem(point,
						cache.getName(), cache.getDescription());
				itemizedOverlay.addOverlay(overlayitem);
			}
		}
	}

	private void initalizeToogleButton() {
		Button rightButton = (Button) findViewById(R.id.toggle_button);
		rightButton.setText(getString(R.string.toggleview));
		rightButton.setOnClickListener(new OnClickListener() {
			@SuppressWarnings("deprecation")
			public void onClick(View v) {
				if (mapView.isSatellite()) {
					mapView.setSatellite(false);
					mapView.setStreetView(true);
				} else {
					mapView.setStreetView(false);
					mapView.setSatellite(true);
				}
			}
		});
	}

}